package cn.cangfei.massage.service.impl;

import cn.cangfei.massage.dto.param.MassageInfoParam;
import cn.cangfei.massage.dto.param.MassageOutpatientRelationParam;
import cn.cangfei.massage.dto.param.MassageSpecialRelationParam;
import cn.cangfei.massage.dto.update.MassageInfoUpdate;
import cn.cangfei.massage.entity.*;
import cn.cangfei.massage.mapper.*;
import cn.cangfei.massage.service.IMassageClinicService;
import cn.cangfei.massage.service.IMassageDoctorService;
import cn.cangfei.massage.service.IMassageInfoService;
import cn.cangfei.massage.service.IMassageOutpatientService;
import cn.cangfei.massage.exception.YyghException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author Lemon  2313812755@qq.com
 * @date 2023/2/3
 */

@Service
public class
MassageInfoServiceImpl implements IMassageInfoService {

    @Resource
    private MassageInfoMapper infoMapper;

    @Resource
    private IMassageClinicService massageClinicService;

    @Resource
    private MassageSpecialRelationMapper specialRelationMapper;

    @Resource
    private IMassageDoctorService doctorService;

    @Resource
    private IMassageOutpatientService outpatientService;

    @Resource
    private MassageOutpatientMapper outpatientMapper;

    @Resource
    private MassageSpecialMapper massageSpecialMapper;

    @Resource
    private MassageOutpatientRelationMapper outpatientRelationMapper;

    @Resource
    private MassageInfoMapper massageInfoMapper;

    @Resource
    private MassageClinicMapper massageClinicMapper;

    @Resource
    private MassageOutpatientRelationMapper massageOutpatientRelationMapper;

    @Resource
    private MassageSpecialRelationMapper massageSpecialRelationMapper;

    /**
     * 添加推拿馆信息
     *
     * @param param 推拿馆信息参数
     * @return 是否成功
     */
    @Transactional
    @Override
    public boolean insert(MassageInfoParam param) {

        // 先判断一下推拿馆名称+推拿馆地址是否已经存在
        LambdaQueryWrapper<MassageInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MassageInfo::getName, param.getName());
        wrapper.eq(MassageInfo::getAddress, param.getAddress());
        MassageInfo massageInfo = massageInfoMapper.selectOne(wrapper);
        if (massageInfo != null) {
            throw new IllegalArgumentException("推拿馆名称+推拿馆地址已经存在");
        }

        MassageInfo info = new MassageInfo();

        BeanUtils.copyProperties(param, info);

        info.setGmtCreate(new Date());
        info.setGmtModified(new Date());
        int insert = massageInfoMapper.insert(info);
        // 得到推拿馆id
        massageInfo = massageInfoMapper.selectOne(wrapper);
        // 推拿馆id
        Long id1 = massageInfo.getId();

        MassageSpecial massageSpecial = new MassageSpecial();
        massageSpecial.setName(param.getName() + param.getAddress());
        massageSpecial.setDescription(param.getName() + param.getAddress());
        massageSpecial.setGmtCreate(new Date());
        massageSpecial.setGmtModified(new Date());
        massageSpecialMapper.insert(massageSpecial);
        // 得到specialId
        LambdaQueryWrapper<MassageSpecial> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(MassageSpecial::getName, param.getName() + param.getAddress());
        MassageSpecial massageSpecial1 = massageSpecialMapper.selectOne(wrapper1);

        Long id2 = massageSpecial1.getId();

        MassageOutpatient massageOutpatient = new MassageOutpatient();
        massageOutpatient.setName(param.getName() + param.getAddress());
        massageOutpatient.setSpecialId(id2);
        massageOutpatient.setGmtCreate(new Date());
        massageOutpatient.setGmtModified(new Date());
        outpatientMapper.insert(massageOutpatient);

        LambdaQueryWrapper<MassageOutpatient> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(MassageOutpatient::getName, param.getName() + param.getAddress());
        MassageOutpatient massageOutpatient1 = outpatientMapper.selectOne(wrapper2);

        // 得到outpatientId
        Long id3 = massageOutpatient1.getId();

        // 添加推拿馆门诊关系
        MassageClinic massageClinic = new MassageClinic();
        massageClinic.setGmtCreate(new Date());
        massageClinic.setGmtModified(new Date());
        massageClinic.setOutpatientId(id3);

        massageClinic.setAddress(param.getName() + param.getAddress());
        massageClinicMapper.insert(massageClinic);


        MassageOutpatientRelation massageOutpatientRelation = new MassageOutpatientRelation();
        massageOutpatientRelation.setMassageId(id1);
        massageOutpatientRelation.setGmtModified(new Date());
        massageOutpatientRelation.setGmtCreate(new Date());
        massageOutpatientRelation.setOutpatientId(id3);
        massageOutpatientRelationMapper.insert(massageOutpatientRelation);

        MassageSpecialRelation massageSpecialRelation = new MassageSpecialRelation();
        massageSpecialRelation.setMassageId(id1);
        massageSpecialRelation.setSpecialId(id2);
        massageSpecialRelation.setGmtCreate(new Date());
        massageSpecialRelation.setGmtModified(new Date());
        massageSpecialRelationMapper.insert(massageSpecialRelation);

        return true;
    }

    /**
     * 更新推拿馆信息
     *
     * @param id    推拿馆编号
     * @param param 推拿馆信息参数
     * @return 是否成功
     */
    @Transactional
    @Override
    public boolean update(Long id, MassageInfoParam param) {
        MassageInfo info = new MassageInfo();

        // 首先判断name和address
        MassageInfo massageInfo = massageInfoMapper.selectById(id);
        String name = massageInfo.getName();
        String address = massageInfo.getAddress();
        if (name.equals(param.getName()) && address.equals(param.getAddress())) {

        } else {
            // 判断里面是否重复
            LambdaQueryWrapper<MassageInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(MassageInfo::getName, param.getName());
            lambdaQueryWrapper.eq(MassageInfo::getAddress, param.getAddress());

            Integer count = massageInfoMapper.selectCount(lambdaQueryWrapper);
            if (count > 0) {
                throw new YyghException(500, "已存在相同的店铺名称和地址");
            }
        }
        // 表示这个是没有修改的
        // 根据massageId查询出outpatientId
        LambdaQueryWrapper<MassageOutpatientRelation> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(MassageOutpatientRelation::getMassageId, id);
        MassageOutpatientRelation massageOutpatientRelation = massageOutpatientRelationMapper.selectOne(wrapper1);
        Long outpatientId = massageOutpatientRelation.getOutpatientId();

        // 修改outpatient表中的name
        LambdaQueryWrapper<MassageOutpatient> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(MassageOutpatient::getId, outpatientId);
        MassageOutpatient massageOutpatient = outpatientMapper.selectOne(wrapper2);
        massageOutpatient.setName(param.getName() + param.getAddress());
        outpatientMapper.updateById(massageOutpatient);

        // 还要修改clinic表中的address
        MassageClinic massageClinic = new MassageClinic();
        massageClinic.setAddress(param.getName() + param.getAddress());
        LambdaQueryWrapper<MassageClinic> wrapper = new LambdaQueryWrapper<>();
        // 需要根据outpatientId来修改
        wrapper.eq(MassageClinic::getOutpatientId, outpatientId);
        massageClinicMapper.update(massageClinic, wrapper);

        // 根据massageId获取specialId
        LambdaQueryWrapper<MassageSpecialRelation> wrapper3 = new LambdaQueryWrapper<>();
        wrapper3.eq(MassageSpecialRelation::getMassageId, id);
        MassageSpecialRelation massageSpecialRelation = massageSpecialRelationMapper.selectOne(wrapper3);
        Long specialId = massageSpecialRelation.getSpecialId();

        // 修改special表中的name和description
        LambdaQueryWrapper<MassageSpecial> wrapper4 = new LambdaQueryWrapper<>();
        wrapper4.eq(MassageSpecial::getId, specialId);
        MassageSpecial massageSpecial = massageSpecialMapper.selectOne(wrapper4);
        massageSpecial.setName(param.getName() + param.getAddress());
        massageSpecial.setDescription(param.getName());
        massageSpecialMapper.updateById(massageSpecial);


        BeanUtils.copyProperties(param, info);

        info.setId(id);
        info.setGmtModified(new Date());

        return infoMapper.updateByPrimaryKeySelective(info) > 0;


    }

    /**
     * 获取推拿馆名称
     *
     * @param id 推拿馆编号
     * @return 推拿馆名称，否则返回未知
     */
    @Override
    public String getName(Long id) {
        return getOptional(id).map(MassageInfo::getName).orElse("未知");
    }

    /**
     * 获取推拿馆信息
     *
     * @param id 推拿馆编号
     * @return 推拿馆信息
     */
    @Override
    public Optional<MassageInfo> getOptional(Long id) {

        return Optional.ofNullable(infoMapper.selectByPrimaryKey(id));
    }

    /**
     * 删除推拿馆信息
     *
     * @param id 推拿馆编号
     * @return 是否成功
     */
    @Transactional
    @Override
    public boolean delete(Long id) {
        // 先去看看有没有师傅在这个推拿馆如果没有的话才能进行删除
        Integer count = doctorService.getDoctorByMassageId(id);
        if (count > 0) {
            throw new YyghException(500, "请先将改诊所的全部师傅删除！");
        }

        // 根据massageId获取outpatientId
        LambdaQueryWrapper<MassageOutpatientRelation> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(MassageOutpatientRelation::getMassageId, id);
        MassageOutpatientRelation massageOutpatientRelation = massageOutpatientRelationMapper.selectOne(wrapper1);
        // 然后删除这个记录
        massageOutpatientRelationMapper.deleteById(massageOutpatientRelation.getId());

        // 获取outpatientId
        Long outpatientId = massageOutpatientRelation.getOutpatientId();

        // 删除outpatient表中的记录
        outpatientMapper.deleteById(outpatientId);

        // 根据outpatientId删除clinic表中的记录
        LambdaQueryWrapper<MassageClinic> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(MassageClinic::getOutpatientId, outpatientId);
        MassageClinic massageClinic = massageClinicMapper.selectOne(wrapper2);
        massageClinicMapper.deleteById(massageClinic.getId());


        // 还要删除其余的关系表
        MassageInfo massageInfo = massageInfoMapper.selectById(id);
        // 先获取massageId然后根据massageId获取specialId
        LambdaQueryWrapper<MassageSpecialRelation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MassageSpecialRelation::getMassageId, id);
        MassageSpecialRelation massageSpecialRelation = massageSpecialRelationMapper.selectOne(wrapper);

        // 然后删除这个记录
        massageSpecialRelationMapper.deleteById(massageSpecialRelation.getId());

        // 得到specialId
        Long specialId = massageSpecialRelation.getSpecialId();

        // 根据specialId删除special表中的记录
        massageSpecialMapper.deleteById(specialId);


        return infoMapper.deleteByPrimaryKey(id) > 0;
    }

    /**
     * 判断电话是否存在
     *
     * @param phone 电话
     * @return 是否存在
     */
    @Override
    public boolean count(String phone) {
        MassageInfoExample example = new MassageInfoExample();

        example.createCriteria()
                .andPhoneEqualTo(phone);

        return infoMapper.countByExample(example) > 0;
    }

    /**
     * 判断推拿馆信息是否存在
     *
     * @param id 推拿馆编号
     * @return 是否存在
     */
    @Override
    public boolean count(Long id) {
        MassageInfoExample example = new MassageInfoExample();

        example.createCriteria()
                .andIdEqualTo(id);

        return infoMapper.countByExample(example) > 0;
    }

    /**
     * 查找推拿馆列表
     *
     * @param name     推拿馆名称
     * @param pageNum  第几页
     * @param pageSize 页大小
     * @return 推拿馆列表
     */
    @Override
    public List<MassageInfo> list(String name, Integer pageNum, Integer pageSize) {

        PageHelper.startPage(pageNum, pageSize);

        MassageInfoExample example = new MassageInfoExample();

        if (!StringUtils.isEmpty(name)) {
            example.createCriteria()
                    .andNameLike("%" + name + "%");

        }

        return infoMapper.selectByExample(example);
    }

    /**
     * 插入专科到推拿馆中去
     *
     * @param param 推拿馆专科关系参数
     * @return 是否成功
     */
    @Override
    public boolean insertSpecialRelation(MassageSpecialRelationParam param) {
        MassageSpecialRelation relation = new MassageSpecialRelation();

        BeanUtils.copyProperties(param, relation);

        relation.setGmtCreate(new Date());
        relation.setGmtModified(new Date());

        return specialRelationMapper.insertSelective(relation) > 0;
    }

    /**
     * 删除从推拿馆中移除专科
     *
     * @param massageId 推拿馆编号
     * @param specialId  专科编号
     * @return 是否成功
     */
    @Override
    public boolean deleteSpecialRelation(Long massageId, Long specialId) {

        MassageSpecialRelationExample example = new MassageSpecialRelationExample();

        example.createCriteria()
                .andMassageIdEqualTo(massageId)
                .andSpecialIdEqualTo(specialId);

        return specialRelationMapper.deleteByExample(example) > 0;
    }

    /**
     * 删除从推拿馆中移除门诊
     *
     * @param massageId   推拿馆编号
     * @param outpatientId 门诊编号
     * @return 是否成功
     */
    @Override
    public boolean deleteOutpatientRelation(Long massageId, Long outpatientId) {

        MassageOutpatientRelationExample example = new MassageOutpatientRelationExample();

        example.createCriteria()
                .andMassageIdEqualTo(massageId)
                .andOutpatientIdEqualTo(outpatientId);

        return outpatientRelationMapper.deleteByExample(example) > 0;
    }

    /**
     * 插入门诊到推拿馆中去
     *
     * @param param 推拿馆门诊关系参数
     * @return 是否成功
     */
    @Override
    public boolean insertOutpatientRelation(MassageOutpatientRelationParam param) {

        MassageOutpatientRelation relation = new MassageOutpatientRelation();

        BeanUtils.copyProperties(param, relation);

        relation.setGmtCreate(new Date());
        relation.setGmtModified(new Date());

        return outpatientRelationMapper.insertSelective(relation) > 0;
    }

    /**
     * 判断关系是否存在
     *
     * @param id 关系编号
     * @return 是否存在
     */
    @Override
    public boolean countSpecialRelation(Long id) {
        MassageSpecialRelationExample example = new MassageSpecialRelationExample();

        example.createCriteria()
                .andIdEqualTo(id);

        return specialRelationMapper.countByExample(example) > 0;
    }

    /**
     * 判断关系是否存在
     *
     * @param id 关系编号
     * @return 是否存在
     */
    @Override
    public boolean countOutpatientRelation(Long id) {
        MassageOutpatientRelationExample example = new MassageOutpatientRelationExample();

        example.createCriteria()
                .andIdEqualTo(id);

        return outpatientRelationMapper.countByExample(example) > 0;
    }

    /**
     * 判断推拿馆是否存在该专科
     *
     * @param param 推拿馆专科关系参数
     * @return 是否存在
     */
    @Override
    public boolean countSpecialRelation(MassageSpecialRelationParam param) {
        MassageSpecialRelationExample example = new MassageSpecialRelationExample();

        example.createCriteria()
                .andMassageIdEqualTo(param.getMassageId())
                .andSpecialIdEqualTo(param.getSpecialId());

        return specialRelationMapper.countByExample(example) > 0;
    }

    /**
     * 判断推拿馆是否存在该门诊
     *
     * @param param 推拿馆门诊关系参数
     * @return 是否存在
     */
    @Override
    public boolean countOutpatientRelation(MassageOutpatientRelationParam param) {
        MassageOutpatientRelationExample example = new MassageOutpatientRelationExample();

        example.createCriteria()
                .andMassageIdEqualTo(param.getMassageId())
                .andOutpatientIdEqualTo(param.getOutpatientId());

        return outpatientRelationMapper.countByExample(example) > 0;
    }

    /**
     * 根据推拿馆id获取推拿馆信息
     *
     * @param massageId
     * @return
     */
    @Override
    public MassageInfoUpdate getMassageById(Long massageId) {

        MassageInfo massageInfo = infoMapper.selectByPrimaryKey(massageId);
        MassageInfoUpdate massageInfoUpdate = new MassageInfoUpdate();
        BeanUtils.copyProperties(massageInfo, massageInfoUpdate);

        // 还要获取到clinicId

        // 获取到outpatient
        List<MassageOutpatient> outpatients = outpatientService.getAllByMassageId(massageId);

        if (outpatients != null && outpatients.size() > 0) {
            // 根据outPatients获取到全部的clinicId
            List<MassageClinic> massageClinics = massageClinicService.getClinicIdsByOutPatients(outpatients);
            if (massageClinics != null && massageClinics.size() > 0) {
                List<Long> collect = massageClinics.stream().map(MassageClinic::getId).collect(Collectors.toList());
                massageInfoUpdate.setClinicList(collect);
            }
        }


        return massageInfoUpdate;
    }
}
